home *** CD-ROM | disk | FTP | other *** search
/ Ian & Stuart's Australian Mac: Not for Sale / Another.not.for.sale (Australia).iso / hold me in your arms / PGP 2.6 / pgp2.6 Source / src / idea.c < prev    next >
C/C++ Source or Header  |  1994-05-12  |  16KB  |  645 lines

  1. /*
  2.  *    idea.c - C source code for IDEA block cipher.
  3.  *    IDEA (International Data Encryption Algorithm), formerly known as 
  4.  *    IPES (Improved Proposed Encryption Standard).
  5.  *    Algorithm developed by Xuejia Lai and James L. Massey, of ETH Zurich.
  6.  *    This implementation modified and derived from original C code 
  7.  *    developed by Xuejia Lai.  
  8.  *    Zero-based indexing added, names changed from IPES to IDEA.
  9.  *    CFB functions added.  Random number routines added.
  10.  *
  11.  *    Extensively optimized and restructured by Colin Plumb.
  12.  *
  13.  *    There are two adjustments that can be made to this code to
  14.  *    speed it up.  Defaults may be used for PCs.  Only the -DIDEA32
  15.  *    pays off significantly if selectively set or not set.
  16.  *    Experiment to see what works best for your machine.
  17.  *
  18.  *    Multiplication: default is inline, -DAVOID_JUMPS uses a
  19.  *        different version that does not do any conditional
  20.  *        jumps (a few percent worse on a SPARC), while
  21.  *        -DSMALL_CACHE takes it out of line to stay
  22.  *        within a small on-chip code cache.
  23.  *    Variables: normally, 16-bit variables are used, but some
  24.  *        machines (notably RISCs) do not have 16-bit registers,
  25.  *        so they do a great deal of masking.  -DIDEA32 uses "int"
  26.  *        register variables and masks explicitly only where
  27.  *        necessary.  On a SPARC, for example, this boosts
  28.  *        performace by 30%.
  29.  *
  30.  *    The IDEA(tm) block cipher is covered by patents held by ETH and a
  31.  *    Swiss company called Ascom-Tech AG.  The Swiss patent number is
  32.  *    PCT/CH91/00117, the European patent number is EP 0 482 154 B1, and
  33.  *    the U.S. patent number is US005214703.  IDEA(tm) is a trademark of
  34.  *    Ascom-Tech AG.  There is no license fee required for noncommercial
  35.  *    use.  Commercial users may obtain licensing details from Dieter
  36.  *    Profos, Ascom Tech AG, Solothurn Lab, Postfach 151, 4502 Solothurn,
  37.  *    Switzerland, Tel +41 65 242885, Fax +41 65 235761.
  38.  *
  39.  *    The IDEA block cipher uses a 64-bit block size, and a 128-bit key 
  40.  *    size.  It breaks the 64-bit cipher block into four 16-bit words
  41.  *    because all of the primitive inner operations are done with 16-bit 
  42.  *    arithmetic.  It likewise breaks the 128-bit cipher key into eight 
  43.  *    16-bit words.
  44.  *
  45.  *    For further information on the IDEA cipher, see the book:
  46.  *      Xuejia Lai, "On the Design and Security of Block Ciphers",
  47.  *      ETH Series on Information Processing (ed. J.L. Massey) Vol 1,
  48.  *      Hartung-Gorre Verlag, Konstanz, Switzerland, 1992.  ISBN
  49.  *      3-89191-573-X.
  50.  *
  51.  *    This code runs on arrays of bytes by taking pairs in big-endian
  52.  *    order to make the 16-bit words that IDEA uses internally.  This
  53.  *    produces the same result regardless of the byte order of the
  54.  *    native CPU.
  55.  */
  56.  
  57. #include "idea.h"
  58. #include "randpool.h"
  59.  
  60. #ifdef IDEA32    /* Use >16-bit temporaries */
  61. #define low16(x) ((x) & 0xFFFF)
  62. typedef unsigned int uint16;    /* at LEAST 16 bits, maybe more */
  63. #else
  64. #define low16(x) (x)    /* this is only ever applied to uint16's */
  65. typedef word16 uint16;
  66. #endif
  67.  
  68. #ifdef _GNUC_
  69. /* __const__ simply means there are no side effects for this function,
  70.  * which is useful info for the gcc optimizer
  71.  */
  72. #define CONST __const__
  73. #else
  74. #define CONST
  75. #endif
  76.  
  77. /*
  78.  *    Multiplication, modulo (2**16)+1
  79.  * Note that this code is structured on the assumption that
  80.  * untaken branches are cheaper than taken branches, and the
  81.  * compiler doesn't schedule branches.
  82.  */
  83. #ifdef SMALL_CACHE
  84. CONST static uint16
  85. mul(register uint16 a, register uint16 b)
  86. {
  87.     register word32 p;
  88.  
  89.     p = (word32)a * b;
  90.     if (p) {
  91.         b = low16(p);
  92.         a = p>>16;
  93.         return (b - a) + (b < a);
  94.     } else if (a) {
  95.         return 1-b;
  96.     } else {
  97.         return 1-a;
  98.     }
  99. } /* mul */
  100. #endif /* SMALL_CACHE */
  101.  
  102. /*
  103.  * Compute the multiplicative inverse of x, modulo 65537, using Euclid's
  104.  * algorithm. It is unrolled twice to avoid swapping the registers each
  105.  * iteration, and some subtracts of t have been changed to adds.
  106.  */
  107. CONST static uint16
  108. mulInv(uint16 x)     
  109. {
  110.     uint16 t0, t1;
  111.     uint16 q, y;
  112.  
  113.     if (x <= 1)
  114.         return x;    /* 0 and 1 are self-inverse */
  115.     t1 = 0x10001L / x;    /* Since x >= 2, this fits into 16 bits */
  116.     y = 0x10001L % x;
  117.     if (y == 1)
  118.         return low16(1-t1);
  119.     t0 = 1;
  120.     do {
  121.         q = x / y;
  122.         x = x % y;
  123.         t0 += q * t1;
  124.         if (x == 1)
  125.             return t0;
  126.         q = y / x;
  127.         y = y % x;
  128.         t1 += q * t0;
  129.     } while (y != 1);
  130.     return low16(1-t1);
  131. } /* mukInv */
  132.  
  133. /*
  134.  * Expand a 128-bit user key to a working encryption key EK
  135.  */
  136. static void
  137. ideaExpandKey(byte const *userkey, word16 *EK)
  138. {
  139.     int i,j;
  140.  
  141.     for (j=0; j<8; j++) {
  142.         EK[j] = (userkey[0]<<8) + userkey[1];
  143.         userkey += 2;
  144.     }
  145.     for (i=0; j < IDEAKEYLEN; j++) {
  146.         i++;
  147.         EK[i+7] = EK[i & 7] << 9 | EK[i+1 & 7] >> 7;
  148.         EK += i & 8;
  149.         i &= 7;
  150.     }
  151. } /* ideaExpandKey */
  152.  
  153. /*
  154.  * Compute IDEA decryption key DK from an expanded IDEA encryption key EK
  155.  * Note that the input and output may be the same.  Thus, the key is
  156.  * inverted into an internal buffer, and then copied to the output.
  157.  */
  158. static void
  159. ideaInvertKey(word16 const *EK, word16 DK[IDEAKEYLEN])
  160. {
  161.     int i;
  162.     uint16 t1, t2, t3;
  163.     word16 temp[IDEAKEYLEN];
  164.     word16 *p = temp + IDEAKEYLEN;
  165.  
  166.     t1 = mulInv(*EK++);
  167.     t2 = -*EK++;
  168.     t3 = -*EK++;
  169.     *--p = mulInv(*EK++);
  170.     *--p = t3;
  171.     *--p = t2;
  172.     *--p = t1;
  173.  
  174.     for (i = 0; i < IDEAROUNDS-1; i++) {
  175.         t1 = *EK++;
  176.         *--p = *EK++;
  177.         *--p = t1;
  178.  
  179.         t1 = mulInv(*EK++);
  180.         t2 = -*EK++;
  181.         t3 = -*EK++;
  182.         *--p = mulInv(*EK++);
  183.         *--p = t2;
  184.         *--p = t3;
  185.         *--p = t1;
  186.     }
  187.     t1 = *EK++;
  188.     *--p = *EK++;
  189.     *--p = t1;
  190.  
  191.     t1 = mulInv(*EK++);
  192.     t2 = -*EK++;
  193.     t3 = -*EK++;
  194.     *--p = mulInv(*EK++);
  195.     *--p = t3;
  196.     *--p = t2;
  197.     *--p = t1;
  198. /* Copy and destroy temp copy */
  199.     memcpy(DK, temp, sizeof(temp));
  200.     burn(temp);
  201. } /* ideaInvertKey */
  202.  
  203. /*
  204.  * MUL(x,y) computes x = x*y, modulo 0x10001.  Requires two temps, 
  205.  * t16 and t32.  x is modified, and must me a side-effect-free lvalue.
  206.  * y may be anything, but unlike x, must be strictly 16 bits even if
  207.  * low16() is #defined.
  208.  * All of these are equivalent - see which is faster on your machine
  209.  */
  210. #ifdef SMALL_CACHE
  211. #define MUL(x,y) (x = mul(low16(x),y))
  212. #else /* !SMALL_CACHE */
  213. #ifdef AVOID_JUMPS
  214. #define MUL(x,y) (x = low16(x-1), t16 = low16((y)-1), \
  215.         t32 = (word32)x*t16 + x + t16 + 1, x = low16(t32), \
  216.         t16 = t32>>16, x = (x-t16) + (x<t16) )
  217. #else /* !AVOID_JUMPS (default) */
  218. #define MUL(x,y) \
  219.     ((t16 = (y)) ? \
  220.         (x=low16(x)) ? \
  221.             t32 = (word32)x*t16, \
  222.             x = low16(t32), \
  223.             t16 = t32>>16, \
  224.             x = (x-t16)+(x<t16) \
  225.         : \
  226.             (x = 1-t16) \
  227.     : \
  228.         (x = 1-x))
  229. #endif
  230. #endif
  231.  
  232. /*    IDEA encryption/decryption algorithm */
  233. /* Note that in and out can be the same buffer */
  234. static void
  235. ideaCipher(byte const (inbuf[8]), byte (outbuf[8]), word16 const *key)
  236. {
  237.     register uint16 x1, x2, x3, x4, s2, s3;
  238.     word16 *in, *out;
  239. #ifndef SMALL_CACHE
  240.     register uint16 t16;    /* Temporaries needed by MUL macro */
  241.     register word32 t32;
  242. #endif
  243.     int r = IDEAROUNDS;
  244.  
  245.     in = (word16 *)inbuf;
  246.     x1 = *in++;  x2 = *in++;
  247.     x3 = *in++;  x4 = *in;
  248. #ifndef HIGHFIRST
  249.     x1 = (x1>>8) | (x1<<8);
  250.     x2 = (x2>>8) | (x2<<8);
  251.     x3 = (x3>>8) | (x3<<8);
  252.     x4 = (x4>>8) | (x4<<8);
  253. #endif
  254.     do {
  255.         MUL(x1,*key++);
  256.         x2 += *key++;
  257.         x3 += *key++;
  258.         MUL(x4, *key++);
  259.  
  260.         s3 = x3;
  261.         x3 ^= x1;
  262.         MUL(x3, *key++);
  263.         s2 = x2;
  264.         x2 ^= x4;
  265.         x2 += x3;
  266.         MUL(x2, *key++);
  267.         x3 += x2;
  268.  
  269.         x1 ^= x2;  x4 ^= x3;
  270.  
  271.         x2 ^= s3;  x3 ^= s2;
  272.     } while (--r);
  273.     MUL(x1, *key++);
  274.     x3 += *key++;
  275.     x2 += *key++;
  276.     MUL(x4, *key);
  277.  
  278.     out = (word16 *)outbuf;
  279. #ifdef HIGHFIRST
  280.     *out++ = x1;
  281.     *out++ = x3;
  282.     *out++ = x2;
  283.     *out = x4;
  284. #else /* !HIGHFIRST */
  285.     x1 = low16(x1);
  286.     x2 = low16(x2);
  287.     x3 = low16(x3);
  288.     x4 = low16(x4);
  289.     *out++ = (x1>>8) | (x1<<8);
  290.     *out++ = (x3>>8) | (x3<<8);
  291.     *out++ = (x2>>8) | (x2<<8);
  292.     *out   = (x4>>8) | (x4<<8);
  293. #endif
  294. } /* ideaCipher */
  295.  
  296. /*-------------------------------------------------------------*/
  297.  
  298. #ifdef TEST
  299.  
  300. #include <stdio.h>
  301. #include <time.h>
  302. /*
  303.  * This is the number of Kbytes of test data to encrypt.
  304.  * It defaults to 1 MByte.
  305.  */
  306. #ifndef BLOCKS
  307. #ifndef KBYTES
  308. #define KBYTES 1024
  309. #endif
  310. #define BLOCKS (64*KBYTES)
  311. #endif
  312.  
  313. int
  314. main(void)
  315. {    /* Test driver for IDEA cipher */
  316.     int i, j, k;
  317.     byte userkey[16];
  318.     word16 EK[IDEAKEYLEN], DK[IDEAKEYLEN];
  319.     byte XX[8], YY[8], ZZ[8];
  320.     clock_t start, end;
  321.     long l;
  322.  
  323.     /* Make a sample user key for testing... */
  324.     for(i=0; i<16; i++)
  325.         userkey[i] = i+1;
  326.  
  327.     /* Compute encryption subkeys from user key... */
  328.     ideaExpandKey(userkey, EK);
  329.     printf("\nEncryption key subblocks: ");
  330.     for (j=0; j<IDEAROUNDS+1; j++) {
  331.         printf("\nround %d:   ", j+1);
  332.         if (j < IDEAROUNDS)
  333.             for(i=0; i<6; i++)
  334.                 printf(" %6u", EK[j*6+i]);
  335.         else
  336.             for(i=0; i<4; i++)
  337.                 printf(" %6u", EK[j*6+i]);
  338.     }
  339.  
  340.     /* Compute decryption subkeys from encryption subkeys... */
  341.     ideaInvertKey(EK, DK);
  342.     printf("\nDecryption key subblocks: ");
  343.     for (j=0; j<IDEAROUNDS+1; j++) {
  344.         printf("\nround %d:   ", j+1);
  345.         if (j < IDEAROUNDS)
  346.             for(i=0; i<6; i++)
  347.                 printf(" %6u", DK[j*6+i]);
  348.         else
  349.             for(i=0; i<4; i++)
  350.                 printf(" %6u", DK[j*6+i]);
  351.     }
  352.  
  353.     /* Make a sample plaintext pattern for testing... */
  354.     for (k=0; k<8; k++)
  355.         XX[k] = k;
  356.  
  357.     printf("\n Encrypting %d bytes (%ld blocks)...", BLOCKS*16, BLOCKS);
  358.     fflush(stdout);
  359.     start = clock();
  360.     memcpy(YY, XX, 8);
  361.     for (l = 0; l < BLOCKS; l++)
  362.         ideaCipher(YY, YY, EK);    /* repeated encryption */
  363.     memcpy(ZZ, YY, 8);
  364.     for (l = 0; l < BLOCKS; l++)
  365.         ideaCipher(ZZ, ZZ, DK);    /* repeated decryption */
  366.     end = clock() - start;
  367.     l = end  / (CLOCKS_PER_SEC/1000) + 1;
  368.     i = l/1000;
  369.     j = l%1000;
  370.     l = (16 * BLOCKS * (CLOCKS_PER_SEC/1000)) / (end/1000);
  371.     printf("%d.%03d seconds = %ld bytes per second\n", i, j, l);
  372.  
  373.     printf("\nX %3u  %3u  %3u  %3u  %3u  %3u  %3u %3u\n",
  374.       XX[0], XX[1],  XX[2], XX[3], XX[4], XX[5],  XX[6], XX[7]);
  375.     printf("\nY %3u  %3u  %3u  %3u  %3u  %3u  %3u %3u\n",
  376.       YY[0], YY[1],  YY[2], YY[3], YY[4], YY[5],  YY[6], YY[7]);
  377.     printf("\nZ %3u  %3u  %3u  %3u  %3u  %3u  %3u %3u\n",    
  378.       ZZ[0], ZZ[1],  ZZ[2], ZZ[3], ZZ[4], ZZ[5],  ZZ[6], ZZ[7]);
  379.  
  380.     /* Now decrypted ZZ should be same as original XX */
  381.     for (k=0; k<8; k++)
  382.         if (XX[k] != ZZ[k]) {
  383.             printf("\n\07Error!  Noninvertable encryption.\n");
  384.             exit(-1);    /* error exit */ 
  385.         }
  386.     printf("\nNormal exit.\n");
  387.     return 0;    /* normal exit */
  388. } /* main */
  389.  
  390. #endif /* TEST */
  391.  
  392.  
  393. /*************************************************************************/
  394.  
  395. void
  396. ideaCfbReinit(struct IdeaCfbContext *context, byte const *iv)
  397. {
  398.     if (iv)
  399.         memcpy(context->iv, iv, 8);
  400.     else
  401.         fill0(context->iv, 8);
  402.     context->bufleft = 0;
  403. }
  404.  
  405. void
  406. ideaCfbInit(struct IdeaCfbContext *context, byte const (key[16]))
  407. {
  408.     ideaExpandKey(key, context->key);
  409.     ideaCfbReinit(context,0);
  410. }
  411.  
  412. void
  413. ideaCfbDestroy(struct IdeaCfbContext *context)
  414. {
  415.     burn(*context);
  416. }
  417.  
  418. /*
  419.  * Okay, explanation time:
  420.  * Phil invented a unique way of doing CFB that's sensitive to semantic
  421.  * boundaries within the data being encrypted.  One way to phrase
  422.  * CFB en/decryption is to say that you XOR the current 8 bytes with
  423.  * IDEA(previous 8 bytes of ciphertext).  Normally, you repeat this
  424.  * at 8-byte intervals, but Phil decided to resync things on the
  425.  * boundaries between elements in the stream being encrypted.
  426.  *
  427.  * That is, the last 4 bytes of a 12-byte field are en/decrypted using
  428.  * the first 4 bytes of IDEA(previous 8 bytes of ciphertext), but then
  429.  * the last 4 bytes of that IDEA computation are thrown away, and the
  430.  * first 8 bytes of the next field are en/decrypted using
  431.  * IDEA(last 8 bytes of ciphertext).  This is equivalent to using a
  432.  * shorter feedback length (if you're familiar with the general CFB
  433.  * technique) briefly, and doesn't weaken the cipher any (using shorter
  434.  * CFB lengths makes it stronger, actually), it just makes it a bit unusual.
  435.  *
  436.  * Anyway, to accomodate this behaviour, every time we do an IDEA
  437.  * encrpytion of 8 bytes of ciphertext to get 8 bytes of XOR mask,
  438.  * we remember the ciphertext.  Then if we have to resync things
  439.  * after having processed, say, 2 bytes, we refill the iv buffer
  440.  * with the last 6 bytes of the old ciphertext followed by the
  441.  * 2 bytes of new ciphertext stored in the front of the iv buffer.
  442.  */
  443. void
  444. ideaCfbSync(struct IdeaCfbContext *context)
  445. {
  446.     int bufleft = context->bufleft;
  447.  
  448.     if (bufleft) {
  449.         memmove(context->iv+bufleft, context->iv, 8-bufleft);
  450.         memcpy(context->iv, context->oldcipher+8-bufleft, bufleft);
  451.         context->bufleft = 0;
  452.     }
  453. }
  454.  
  455. /*
  456.  * Encrypt a buffer of data, using IDEA in CFB mode.
  457.  * There are more compact ways of writing this, but this is
  458.  * written for speed.
  459.  */
  460. void
  461. ideaCfbEncrypt(struct IdeaCfbContext *context, byte const *src,
  462.            byte *dest, int count)
  463. {
  464.     int bufleft = context->bufleft;
  465.     byte *bufptr = context->iv + 8-bufleft;
  466.  
  467.     /* If there are no more bytes to encrypt that there are bytes
  468.      * in the buffer, XOR them in and return.
  469.      */
  470.     if (count <= bufleft) {
  471.         context->bufleft = bufleft - count;
  472.         while (count--) {
  473.             *dest++ = *bufptr++ ^= *src++;
  474.         }
  475.         return;
  476.     }
  477.     count -= bufleft;
  478.     /* Encrypt the first bufleft (0 to 7) bytes of the input by XOR
  479.      * with the last bufleft bytes in the iv buffer.
  480.      */
  481.     while (bufleft--) {
  482.         *dest++ = (*bufptr++ ^= *src++);
  483.     }
  484.     /* Encrypt middle blocks of the input by cranking the cipher,
  485.      * XORing 8-byte blocks, and repeating until the count
  486.      * is 8 or less.
  487.      */
  488.     while (count > 8) {
  489.         bufptr = context->iv;
  490.         memcpy(context->oldcipher, bufptr, 8);
  491.         ideaCipher(bufptr, bufptr, context->key);
  492.         bufleft = 8;
  493.         count -= 8;
  494.         do {
  495.             *dest++ = (*bufptr++ ^= *src++);
  496.         } while (--bufleft);
  497.     }
  498.     /* Do the last 1 to 8 bytes */
  499.     bufptr = context->iv;
  500.     memcpy(context->oldcipher, bufptr, 8);
  501.     ideaCipher(bufptr, bufptr, context->key);
  502.     context->bufleft = 8-count;
  503.     do  {
  504.         *dest++ = (*bufptr++ ^= *src++);
  505.     } while (--count);
  506. }
  507.  
  508.  
  509. /*
  510.  * Decrypt a buffer of data, using IDEA in CFB mode.
  511.  * There are more compact ways of writing this, but this is
  512.  * written for speed.
  513.  */
  514. void
  515. ideaCfbDecrypt(struct IdeaCfbContext *context, byte const *src,
  516.            byte *dest, int count)
  517. {
  518.     int bufleft = context->bufleft;
  519.     static byte *bufptr;
  520.     byte t;
  521.  
  522.     bufptr = context->iv + (8-bufleft);
  523.     if (count <= bufleft) {
  524.         context->bufleft = bufleft - count;
  525.         while (count--) {
  526.             t = *bufptr;
  527.             *dest++ = t ^ (*bufptr++ = *src++);
  528.         }
  529.         return;
  530.     }
  531.     count -= bufleft;
  532.     while (bufleft--) {
  533.         t = *bufptr;
  534.         *dest++ = t ^ (*bufptr++ = *src++);
  535.     }
  536.     while (count > 8) {
  537.         bufptr = context->iv;
  538.         memcpy(context->oldcipher, bufptr, 8);
  539.         ideaCipher(bufptr, bufptr, context->key);
  540.         bufleft = 8;
  541.         count -= 8;
  542.         do {
  543.             t = *bufptr;
  544.             *dest++ = t ^ (*bufptr++ = *src++);
  545.         } while (--bufleft);
  546.     }
  547.     bufptr = context->iv;
  548.     memcpy(context->oldcipher, bufptr, 8);
  549.     ideaCipher(bufptr, bufptr, context->key);
  550.     context->bufleft = 8-count;
  551.     do {
  552.         t = *bufptr;
  553.         *dest++ = t ^ (*bufptr++ = *src++);
  554.     } while (--count);
  555. }
  556.  
  557. /********************************************************************/
  558.  
  559. /*
  560.  * Cryptographically strong pseudo-random-number generator.
  561.  * The design is from Appendix C of ANSI X9.17, "Financial
  562.  * Institution Key Management (Wholesale)", with IDEA
  563.  * substituted for the DES.
  564.  */
  565.  
  566. /*
  567.  * Initialize a cryptographic random-number generator.
  568.  * key and seed should be arbitrary.
  569.  */
  570. void
  571. ideaRandInit(struct IdeaRandContext *context, byte const (key[16]),
  572.          byte const (seed[8]))
  573. {
  574.     int i;
  575.  
  576.     ideaExpandKey(key, context->key);
  577.     context->bufleft = 0;
  578.     memcpy(context->internalbuf, seed, 8);
  579. }
  580.  
  581.  
  582. /*
  583.  * Read out the RNG's state.
  584.  */
  585. void
  586. ideaRandState(struct IdeaRandContext *context, byte key[16], byte seed[8])
  587. {
  588.     int i;
  589.  
  590.     memcpy(seed, context->internalbuf, 8);
  591.     for (i = 0; i < 8; i++) {
  592.         key[2*i] = context->key[i] >> 8;
  593.         key[2*i+1] = context->key[i];
  594.     }
  595.  
  596. }
  597.  
  598. /*
  599.  * Encrypt the RNG's state with the given CFB encryptor.
  600.  */
  601. void
  602. ideaRandWash(struct IdeaRandContext *context, struct IdeaCfbContext *cfb)
  603. {
  604.     byte keyseed[16+8];
  605.     int i;
  606.  
  607.     ideaRandState(context, keyseed, keyseed+16);
  608.     ideaCfbEncrypt(cfb, keyseed, keyseed, 16+8);
  609.     ideaRandInit(context, keyseed, keyseed+16);
  610.  
  611.     memset(keyseed, 0, 16+8);
  612. }
  613.  
  614. /*
  615.  * Cryptographic pseudo-random-number generator, used for generating
  616.  * session keys.
  617.  */
  618. byte
  619. ideaRandByte(struct IdeaRandContext *c)
  620. {
  621.     int i;
  622.  
  623.     if (!c->bufleft) {
  624.         byte timestamp[8];
  625.     
  626.         /* Get some true-random noise to help */
  627.         randPoolGetBytes(timestamp, sizeof(timestamp));
  628.  
  629.         /* Compute next 8 bytes of output */
  630.         for (i=0; i<8; i++)
  631.             c->outbuf[i] = c->internalbuf[i] ^ timestamp[i];
  632.         ideaCipher(c->outbuf, c->outbuf, c->key);
  633.         /* Compute new seed vector */
  634.         for (i=0; i<8; i++)
  635.             c->internalbuf[i] = c->outbuf[i] ^ timestamp[i];
  636.         ideaCipher(c->internalbuf, c->internalbuf, c->key);
  637.         burn(timestamp);
  638.         c->bufleft = 8;
  639.     }
  640.     return c->outbuf[--c->bufleft];
  641. }
  642.  
  643. /* end of idea.c */
  644.  
  645.